﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Sym_i2c
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        #region Pola
        char bus;  //zmienna magistrali
        char scl;
        char sda;
        List<Slave> slaveList = new List<Slave>();  //lista urzadzen slave
        string sdaHistory="";
        string sclHistory="";
        Slave master = new Slave(127);
        Crc firstMessage;
        Crc secondMessage;
        int time=500;
        #endregion
        void start()
        {
            sda = '1';
            labelSDA.Text = "SDA:1";
            sdaHistory += sda;
            scl = '1';
            labelSCL.Text = "SCL:1";
            sclHistory += scl;
            Thread.Sleep(time/2);
            this.Refresh();
            sda = '0';
            labelSDA.Text = "SDA:0";
            sclHistory += scl;
            sdaHistory += sda;
            Thread.Sleep(time/2);
        }
        void stop()
        {
            sda = '0';
            labelSDA.Text = "SDA:0";
            sdaHistory += sda;
            scl = '1';
            labelSCL.Text = "SCL:1";
            sclHistory += scl;
            Thread.Sleep(time/2);
            this.Refresh();
            sda = '1';
            labelSDA.Text = "SDA:1";
            sclHistory += scl;
            sdaHistory += sda;
            Thread.Sleep(time/2);
        }
        void send_1()
        {
            sda = '0';
            labelSDA.Text = "SDA:0";
            sdaHistory += sda;
            scl = '0';
            labelSCL.Text = "SCL:0";
            sclHistory += scl;
            Thread.Sleep(time/2);
            this.Refresh();
            sda = '1';
            labelSDA.Text = "SDA:1";
            sdaHistory += sda;
            Thread.Sleep(time/2);
        }
        void send_0()
        {
            sda = '1';
            labelSDA.Text = "SDA:1";
            sdaHistory += sda;
            scl = '0';
            labelSCL.Text = "SCL:0";
            sclHistory += scl;
            Thread.Sleep(time/2);
            this.Refresh();
            sda = '0';
            labelSDA.Text = "SDA:0";
            sdaHistory += sda;
            Thread.Sleep(time/2);
        }
        // funkcja tworzaca ramke do wyslania
        void send(string message)
        {
            labelMagistrala.Visible = true;
            progressBarTransmission.Minimum = 1;
            progressBarTransmission.Step = 1;
            progressBarTransmission.Maximum = message.Length;
            progressBarTransmission.Visible = true;
            labelSCL.Visible = true;
            labelSDA.Visible = true;
            start();
            for (int i = 0; i < message.Length; i++)
            {
                bus = message[i];
                if(bus=='0'){
                    send_0();
                    pictureBoxLamp.Load(@"C:\Users\Maciek\Documents\Visual Studio 2010\Projects\Symulator\Sym_i2c\data\czerwona_lampka.png");
                    labelBusState.Text = "0";
                    labelBusState.Visible = true;
                }
                if (bus == '1')
                {
                    send_1();
                    labelBusState.Text = "1";
                    labelBusState.Visible = true;
                    pictureBoxLamp.Load(@"C:\Users\Maciek\Documents\Visual Studio 2010\Projects\Symulator\Sym_i2c\data\zielona_lampka.png");
                }
                progressBarTransmission.PerformStep();
                //Thread.Sleep(time);
                //this.Refresh();
            }
            stop();
            if (messageReceived() == true)
            {
                progressBarTransmission.Value = progressBarTransmission.Minimum;
                MessageBox.Show("Zakonczono przesyłanie!");
            }
        }

        bool messageReceived()
        {
            if ((sclHistory[sclHistory.Length - 1] == '1' && sclHistory[sclHistory.Length - 2] == '1')
                && (sdaHistory[sdaHistory.Length - 1] == '1' && sdaHistory[sdaHistory.Length - 2] == '0'))
                return true;
            else
                return false;
        }

           //Sprawdzanie czy wysapil bajt konca
        string formFrame()
        {
            string ack = "1";
            string frame="";
            string adres="";
            string functionCode;
            functionCode = comboBoxFunction.SelectedItem.ToString();
            int stringLength = functionCode.Length;
            string hex = (functionCode.ElementAt(stringLength-3).ToString() + functionCode.ElementAt(stringLength-2).ToString());
            string bin = hexToBin(hex);
            while (bin.Length < 8)
                bin += "0";
            for (int i = 0; i < 7; i++)
			{
			    adres+=comboBoxAddress.SelectedItem.ToString()[i]; 
			}

            frame += adres;
            string ReadWrite;
            if (checkBoxRead.Checked == true)
            {
                ReadWrite = "1";
                frame += ReadWrite;
            }
            if (checkBoxWrite.Checked == true)
            {
                ReadWrite = "0";
                frame += ReadWrite;
            }
            frame+=ack;
            frame += bin;
            frame += data(hex,adres);
            firstMessage = new Crc(frame);
            frame += firstMessage.createCrc();
            analyze(frame);
            return frame;
        }
        string hexToBin(string hex)
        {
            return Convert.ToString(Convert.ToInt32(hex, 16), 2).PadLeft(8, '0');
        }
        string data(string function, string address)
        {
            string data = "";
            switch (function)
            {
                case "00":
                    return data;
                case "10":
                    //adres komórki pamieci
                    Form10h forma = new Form10h();
                    if (forma.ShowDialog() == DialogResult.OK)
                    {
                        string decData10h = forma.Nazwa;
                        data = Convert.ToString(Convert.ToInt32(decData10h), 2).PadLeft(8,'0');
                    }
                    return data;
                case "20":
                    return data;
                case "30":
                    //adres poczatkowy
                    //adres koncowy
                    Form30h form = new Form30h();
                    if (form.ShowDialog() == DialogResult.OK)
                    {
                        string decData30h_1 = form.Begin;
                        data = Convert.ToString(Convert.ToInt32(decData30h_1), 2).PadLeft(8, '0');
                        string decData30h_2 = form.End;
                        data += Convert.ToString(Convert.ToInt32(decData30h_2), 2).PadLeft(8, '0');
                    }
                    int first = Convert.ToInt32(form.Begin);
                    int last = Convert.ToInt32(form.End);
                    Slave slaveSearched = slaveList.Find(x => x.address == address);
                    for (int i = first; i <=last; i++)
                    {
                        for (int j = 0; j < 8; j++)
                        {

                            data += slaveSearched.memory[i, j];
                        }
                        
                    }
                    return data;
                case "01":
                    Form01h form01h = new Form01h();
                    if (form01h.ShowDialog() == DialogResult.OK)
                    {
                        data = form01h.byteString;
                    }
                    return data;
                case "11":
                    Form11h form11h = new Form11h();
                    if (form11h.ShowDialog() == DialogResult.OK)
                    {
                        string decData11h = form11h.memoryAddress;
                        string decData11h_h = form11h.dataByte;
                        data = Convert.ToString(Convert.ToInt32(decData11h), 2).PadLeft(8, '0');
                        string decData11h_2 = form11h.dataByte;
                        data += decData11h_2;
                    }
                    return data;
                case "21":
                    Form21h form21h = new Form21h();
                    if (form21h.ShowDialog() == DialogResult.OK)
                    {
                        data = form21h.dataByte;
                    }
                    return data;
                case "31":
                    Form31h form31h = new Form31h();
                    if (form31h.ShowDialog() == DialogResult.OK)
                    {
                        string decData31h = form31h.Begin;
                        data += Convert.ToString(Convert.ToInt32(decData31h), 2).PadLeft(8, '0');
                        string decData31h_2 = form31h.End;
                        data += Convert.ToString(Convert.ToInt32(decData31h_2), 2).PadLeft(8, '0');
                        string s;
                        s = form31h.Block.ToString();
                        s = s.Replace("\n", String.Empty);
                        s = s.Replace("\r", String.Empty);
                        s = s.Replace("\t", String.Empty);
                        data += s;
                    }
                    return data;
                case "A0":
                    return data;




                default:
                    return data;
                    break;
            }
        }

        string broadcast(string message)
        {
            string adres;
            StringBuilder modify = new StringBuilder(message);
            for (int i = 0; i < slaveList.Count; i++)
            {
                modify.Remove(0, 7);
                adres = slaveList[i].address;
                modify.Insert(0, adres);
                analyze(modify.ToString());
            }
            return "";
        }

        string analyze(string message)
        {
            int iter=0;;
            string answer="";
            string address = "";
            string function = "";
            for (; iter < 7; iter++)
			{
                address += message[iter];
			}
            if (address == "0000000")
                broadcast(message);
            else
            {
                for (int i = 0; i < slaveList.Count; i++)
                {
                    if (address == slaveList[i].address)
                    {
                        iter++; // R/W bit
                        iter++; //ACK bit
                        //wczytanie kodu funkcji
                        for (int counter = iter; iter < counter + 8; iter++)
                        {
                            function += message[iter];
                        }
                        switch (function)
                        {
                            case "00000000":
                                answer += address;
                                answer += "00000000"; //binarny kod funkcji 00h
                                for (int j = 0; j < 8; j++) // dodanie rejestru slave do ramki
                                {
                                    master.registry[j] = slaveList[i].registry[j];
                                    answer += slaveList[i].registry[j];
                                }
                                secondMessage = new Crc(answer);
                                answer += secondMessage.createCrc();
                                return answer;
                            case "00010000": //10h
                                string stringMemoryAddress = "";
                                int memoryAddress;
                                answer += address;
                                answer += "00010000";
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    stringMemoryAddress += message[iter];
                                }
                                answer += stringMemoryAddress;
                                memoryAddress = Convert.ToInt32(stringMemoryAddress, 2);
                                for (int j = 0; j < 8; j++) // zapisanie w pamieci mastera pamiec slava
                                {
                                    master.memory[memoryAddress, j] = slaveList[i].memory[memoryAddress, j];
                                    answer += slaveList[i].memory[memoryAddress, j];
                                }
                                return answer;
                            case "00100000": //20h
                                answer += address;
                                answer += "00100000";
                                string memoryAddress_20h = "";
                                for (int j = 0; j < 8; j++)
                                    memoryAddress_20h += slaveList[i].registry[j];
                                answer += memoryAddress_20h;
                                string memory = "";
                                int decMemoryAddress_20h = Convert.ToInt32(memoryAddress_20h, 2);
                                for (int j = 0; j < 8; j++)
                                {
                                    memory += slaveList[i].memory[decMemoryAddress_20h, j];
                                    master.memory[decMemoryAddress_20h, j] = slaveList[i].memory[decMemoryAddress_20h, j]; // skopiowanie pamieci do mastera
                                }
                                answer += memory;
                                return answer;
                            case "00110000": //30h
                                string addressBegin = "";
                                string addressEnd = "";
                                answer += address;
                                answer += "00110000";
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    addressBegin += message[iter];
                                }
                                answer += addressBegin;
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    addressEnd += message[iter];
                                }
                                answer += addressEnd;
                                string dataBlock = "";
                                int decAddressEnd = Convert.ToInt32(addressEnd, 2);
                                int decAddressBegin = Convert.ToInt32(addressBegin, 2);
                                for (int j = decAddressBegin; j <= decAddressEnd; j++)
                                {
                                    for (int k = 0; k < 8; k++)
                                    {
                                        master.memory[j, k] = slaveList[i].memory[j, k];
                                        dataBlock += slaveList[i].memory[j, k];
                                    }
                                }
                                answer += dataBlock;
                                return answer;
                            case "00000001": // 01h
                                string stringDataByte = "";
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    stringDataByte += message[iter];
                                }
                                for (int j = 0; j < 8; j++) // zapisanie bajtu w rejestrze
                                {
                                    slaveList[i].registry[j] = stringDataByte[j].ToString();
                                    answer += stringDataByte[j].ToString();
                                }
                                break;
                            case "00010001": //11h
                                stringDataByte = "";
                                stringMemoryAddress = "";
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    stringMemoryAddress += message[iter];
                                }
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    stringDataByte += message[iter];
                                }
                                for (int j = 0; j < 8; j++) // zapisanie bajtu w pamieci
                                {
                                    slaveList[i].memory[Convert.ToInt32(stringMemoryAddress, 2), j] = stringDataByte[j].ToString();
                                }
                                break;
                            case "00100001": //21h
                                stringDataByte = "";
                                stringMemoryAddress = "";
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    stringMemoryAddress += slaveList[i].registry[j];
                                }
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    stringDataByte += message[iter];
                                }
                                answer += stringDataByte;
                                for (int j = 0; j < 8; j++) // zapisanie bajtu w paieci
                                {
                                    slaveList[i].memory[Convert.ToInt32(stringMemoryAddress, 2), j] = stringDataByte[j].ToString();
                                }
                                break;
                            case "00110001"://31h
                                addressBegin = "";
                                addressEnd = "";
                                dataBlock = "";
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    addressBegin += message[iter];
                                }
                                for (int j = 0; j < 8; j++, iter++)
                                {
                                    addressEnd += message[iter];
                                }
                                for (int j = 0; j < 8 * ((Convert.ToInt32(addressEnd, 2) - Convert.ToInt32(addressBegin, 2)) + 1); j++, iter++)
                                {
                                    dataBlock += message[iter];
                                }
                                int l = 0;
                                for (int j = Convert.ToInt32(addressBegin, 2); j <= Convert.ToInt32(addressEnd, 2); j++)
                                {
                                    for (int k = 0; k < 8; k++, l++)
                                    {
                                        slaveList[i].memory[j, k] = dataBlock[l].ToString();
                                    }
                                }
                                break;
                            case "10100000":
                                for (int j = 0; j < 8; j++)
                                {
                                    slaveList[i].registry[j] = "0";
                                }
                                break;
                            default:
                                break;
                        }
                        return answer;
                    }

                }
            }
            return answer;

        }
        #region DGV & Combobox & SlaveList
        private void buttonAdd_Click(object sender, EventArgs e)
        {
            int number = slaveList.Count + 1;
            Slave newItem = new Slave(number);
            newItem.name = "<Urzadzenie slave>";
            slaveList.Add(newItem);
            DataGridViewRow row = (DataGridViewRow)dataGridViewSlaves.Rows[0].Clone();
            row.Cells[0].Value = newItem.number;
            row.Cells[1].Value = newItem.name.ToString();
            row.Cells[2].Value = newItem.address.ToString();
            dataGridViewSlaves.Rows.Add(row);
            //wrzucenie adresow do comboboxa
            comboBoxAddress.Items.Clear();
            comboBoxAddress2.Items.Clear();
            System.Object[] AddressList = new System.Object[slaveList.Count];
            if (slaveList.Count != 0)
            {
                int i;
                for (i = 0; i < slaveList.Count; i++)
                {
                    AddressList[i] = slaveList[i].address + " - " + slaveList[i].name;
                }
                comboBoxAddress.Items.AddRange(AddressList);
                comboBoxAddress2.Items.AddRange(AddressList);
                comboBoxAddress.Items.Add("0000000 - Broadcast");
                comboBoxAddress2.Items.Add("Master");
            }
        }
        private void buttonDelate_Click(object sender, EventArgs e)
        {
            DataGridViewSelectedRowCollection selected = dataGridViewSlaves.SelectedRows;
            //wywalenie danych z dataGridView
            while (dataGridViewSlaves.Rows.Count != 1)
            {
                dataGridViewSlaves.Rows.RemoveAt(0);
            }

            for (int i = 0; i < selected.Count; i++)
            {
                string itemToDelate;
                itemToDelate = selected[i].Cells[0].Value.ToString();
                for (int j = 0; j < slaveList.Count; j++)
                {
                    if (slaveList.ElementAt(j).number == itemToDelate)
                    {
                        //ususniecie slavow z listy
                        slaveList.RemoveAt(j);
                        comboBoxAddress.Items.RemoveAt(j);
                    }
                }
            }
            //rzucenie do dataGridView zaaktualizowanej listy slavow
            for (int i = 0; i < slaveList.Count; i++)
            {
                DataGridViewRow row = (DataGridViewRow)dataGridViewSlaves.Rows[0].Clone();
                slaveList[i].number = (i + 1).ToString();
                slaveList[i].assignAddresses();
                row.Cells[0].Value = slaveList[i].number;
                row.Cells[1].Value = slaveList[i].name;
                row.Cells[2].Value = slaveList[i].address;
                dataGridViewSlaves.Rows.Add(row);
            }
            //aktualizacja comboboxa z adresami
            comboBoxAddress.Items.Clear();
            comboBoxAddress2.Items.Clear();
            System.Object[] AddressList = new System.Object[slaveList.Count];
            if (slaveList.Count != 0)
            {
                int i;
                for (i = 0; i < slaveList.Count; i++)
                {
                    AddressList[i] = slaveList[i].address + " - " + slaveList[i].name;
                }
                comboBoxAddress.Items.AddRange(AddressList);
                comboBoxAddress.Items.Add("0000000 - Broadcast");
                comboBoxAddress2.Items.Add("Master");
                comboBoxAddress2.Items.AddRange(AddressList);
            }
        }
        private void dataGridViewSlaves_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            //Mozliwosc zmiany nazwy w datagridview dla slava

            DataGridViewCell edited = dataGridViewSlaves.CurrentCell;
            int row = edited.RowIndex;
            int column = edited.ColumnIndex;
            string newName;
            newName = dataGridViewSlaves[column, row].Value.ToString();
            string number = dataGridViewSlaves.Rows[row].Cells[0].ToString();
            for (int j = 0; j < slaveList.Count; j++)
            {
                if (slaveList.ElementAt(j).number == number)
                    slaveList.ElementAt(j).name = newName;
            }
            slaveList.ElementAt(row).name = newName;
            //aktualizacja comboboxa
            comboBoxAddress.Items.Clear();
            comboBoxAddress2.Items.Clear();
            System.Object[] AddressList = new System.Object[slaveList.Count];
            if (slaveList.Count != 0)
            {
                int i;
                for (i = 0; i < slaveList.Count; i++)
                {
                    AddressList[i] = slaveList[i].address + " - " + slaveList[i].name;
                }
                comboBoxAddress.Items.AddRange(AddressList);
                comboBoxAddress.Items.Add("0000000 - Broadcast");
                comboBoxAddress2.Items.Add("Master");
                comboBoxAddress2.Items.AddRange(AddressList);

            }
        }
        private void buttonFormFrame_Click(object sender, EventArgs e)
        {
            if (((comboBoxAddress.SelectedIndex > -1) == false) || ((comboBoxFunction.SelectedIndex > -1) == false))
                MessageBox.Show("Wybierz adres urządzenia oraz funkcję ! ", "Warning !", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            else
            {
                if ((checkBoxRead.Checked == true && checkBoxWrite.Checked == true) || (checkBoxRead.Checked == false && checkBoxWrite.Checked == false))
                    MessageBox.Show("Zaznacz poprawnie bit zapisu/odczytu");
                else
                {
                    MessageBox.Show(formatFrame(formFrame()));
                }
            }
        }
        private void buttonSend_Click(object sender, EventArgs e)
        {
            if (((comboBoxAddress.SelectedIndex > -1) == false) || ((comboBoxFunction.SelectedIndex > -1) == false))
                MessageBox.Show("Wybierz adres urządzenia oraz funkcję ! ", "Warning !", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            else
            {
                if ((checkBoxRead.Checked == true && checkBoxWrite.Checked == true) || (checkBoxRead.Checked == false && checkBoxWrite.Checked == false))
                    MessageBox.Show("Zaznacz poprawnie bit zapisu/odczytu");
                else
                {
                    string frame=formFrame();
                    MessageBox.Show(formatFrame(frame));
                    send(frame);
                }
            }
        }
        public string formatFrame(string frame)
        {
            System.Text.StringBuilder sb;
            sb = new StringBuilder();
            sb.Append(frame);
            sb.Insert(7, " | ");
            sb.Insert(11, " | ");
            sb.Insert(15, " | ");
            sb.Insert(26, " | ");
            sb.Insert(sb.Length - 8, " | ");
            return sb.ToString();
        }
        private void buttonReadRegistry_Click(object sender, EventArgs e)
        {
            string registry = "";
            if((comboBoxAddress2.SelectedIndex > -1 )== false)
                MessageBox.Show("Wybierz adres urządzenia, którego pamięć chcesz odczytać ! ", "Warning !", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            else
            {
                if (comboBoxAddress2.SelectedItem.ToString() == "Master")
                {
                    for (int i = 0; i < 8; i++)
                    {
                        registry += master.registry[i];
                    }
                    MessageBox.Show("Rejestr mastera: " + registry, "Rejestr slave'a");
                }
                else
                {
                    string adres = "";
                    for (int i = 0; i < 7; i++)
                    {
                        adres += comboBoxAddress2.SelectedItem.ToString()[i];
                    }
                    Slave slaveSearched = slaveList.Find(x => x.address == adres);
                    for (int i = 0; i < 8; i++)
                    {
                        registry += slaveSearched.registry[i]; ;
                    }
                    MessageBox.Show("Rejestr wybranego slave'a: " + registry, "Rejestr slave'a");
                }
            }
        }
        private void buttonReadMemory_Click(object sender, EventArgs e)
        {
            string memory = "";
            if (String.IsNullOrEmpty(textBoxMemoryAddress.Text.Trim()))
                MessageBox.Show("Wpisz adres pamięci, który chcesz odczytać ! ","Warning !",MessageBoxButtons.OK,MessageBoxIcon.Warning);
            else
            {
                if (comboBoxAddress2.SelectedItem.ToString() == "Master")
                {
                    for (int i = 0; i < 8; i++)
                    {
                        memory += master.memory[Convert.ToInt32(textBoxMemoryAddress.Text), i];
                    }
                    MessageBox.Show("Pamięć kómórki [" + textBoxMemoryAddress.Text + "] mastera: " + memory, "Pamięć mastera");
                }
                else
                {
                    string adres = "";
                    for (int i = 0; i < 7; i++)
                    {
                        adres += comboBoxAddress2.SelectedItem.ToString()[i];
                    }
                    Slave slaveSearched = slaveList.Find(x => x.address == adres);
                    for (int i = 0; i < 8; i++)
                    {
                        memory += slaveSearched.memory[Convert.ToInt32(textBoxMemoryAddress.Text), i];
                    }
                    MessageBox.Show("Pamięć kómórki [" + textBoxMemoryAddress.Text + "] wybranego slave'a: " + memory, "Pamięć slave'a");
                }
            }
        }
        #endregion

        private void trackBarTime_ValueChanged(object sender, EventArgs e)
        {
            time = trackBarTime.Value;
            labelTimeValue.Text = trackBarTime.Value.ToString() + "ms";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

       

    }
}
        
       
